/**
 * Created by uptain on 2017/8/15.
 */
/*!
 * mobileSelect.js
 * (c) 2017-present onlyhom
 * Released under the MIT License.
 */

window.MobileSelect = (function() {

    function getClass(dom,string) {
        return dom.getElementsByClassName(string);
    }

    //构造器
    function MobileSelect(config) {
        this.mobileSelect;
        this.wheelsData = config.wheels;
        this.jsonType =  false;
        this.cascadeJsonData = [];
        this.checkDataType();
        this.renderWheels(this.wheelsData);
        this.displayJson = [];
        this.cascade = false;
        this.startY;
        this.moveEndY;
        this.moveY;
        this.oldMoveY;
        this.offset = 0;
        this.offsetSum = 0;
        this.oversizeBorder;
        this.curDistance = [];
        this.clickStatus = false;

        this.init(config);
    }

    MobileSelect.prototype = {
        constructor: MobileSelect,
        init: function(config){
            var _this = this;

            _this.trigger = document.querySelector(config.trigger);
            _this.wheel = getClass(_this.mobileSelect,'wheel');   //wheel 数组
            _this.slider = getClass(_this.mobileSelect,'selectContainer'); // slider 数组
            _this.wheels = _this.mobileSelect.querySelector('.wheels');   //wheels
            _this.liHeight = _this.mobileSelect.querySelector('li').offsetHeight;
            _this.ensureBtn = _this.mobileSelect.querySelector('.ensure');
            _this.closeBtn = _this.mobileSelect.querySelector('.cancel');
            _this.grayLayer = _this.mobileSelect.querySelector('.grayLayer');
            _this.popUp = _this.mobileSelect.querySelector('.content');
            _this.callback = config.callback ? config.callback : function(){};
            _this.transitionEnd = config.transitionEnd ? config.transitionEnd : function(){};
            _this.initPosition = config.position ? config.position : [];
            _this.titleText = config.title ? config.title : '';

            _this.trigger.style.cursor='pointer';
            _this.setTitle(_this.titleText);
            _this.checkCascade();

            if (_this.cascade) {
                _this.initCascade();
            }

            //定位 初始位置
            if(_this.initPosition.length < _this.slider.length){
                var diff = _this.slider.length - _this.initPosition.length;
                for(var i=0; i<diff; i++){
                    _this.initPosition.push(0);
                }
            }

            _this.setCurDistance(_this.initPosition);
            _this.addListenerAll();

            //按钮监听
            _this.closeBtn.addEventListener('click',function(){
                _this.mobileSelect.classList.remove('mobileSelect-show');
            });

            _this.ensureBtn.addEventListener('click',function(){
                _this.mobileSelect.classList.remove('mobileSelect-show');
                var tempValue ='';
                for(var i=0; i<_this.wheel.length; i++){
                    i==_this.wheel.length-1 ? tempValue += _this.getValue(i) : tempValue += _this.getValue(i)+' ';
                }
                _this.trigger.innerHTML = tempValue;
                _this.callback(_this.getIndexArr(),_this.getResult());
            });

            _this.trigger.addEventListener('click',function(){
                _this.mobileSelect.classList.add('mobileSelect-show');
            });
            _this.grayLayer.addEventListener('click',function(){
                _this.mobileSelect.classList.remove('mobileSelect-show');
            });
            _this.popUp.addEventListener('click',function(){
                event.stopPropagation();
            });

            _this.fixRowStyle(); //修正列数
        },

        setTitle: function(string){
            var _this = this;
            _this.titleText = string;
            _this.mobileSelect.querySelector('.title').innerHTML = _this.titleText;
        },

        show: function(){
            this.mobileSelect.classList.add('mobileSelect-show');
        },

        renderWheels: function(wheelsData){
            var _this = this;
            _this.mobileSelect = document.createElement("div");
            _this.mobileSelect.className = "mobileSelect";
            _this.mobileSelect.innerHTML =
                '<div class="grayLayer"></div>'+
                '<div class="content">'+
                '<div class="btnBar">'+
                '<div class="fixWidth">'+
                '<div class="cancel">取消</div>'+
                '<div class="title"></div>'+
                '<div class="ensure">选择</div>'+
                '</div>'+
                '</div>'+
                '<div class="panel">'+
                '<div class="fixWidth">'+
                '<div class="wheels">'+
                '</div>'+
                '<div class="selectLine"></div>'+
                '<div class="shadowMask"></div>'+
                '</div>'+
                '</div>'+
                '</div>';
            document.body.appendChild(_this.mobileSelect);

            //根据数据长度来渲染

            var tempHTML='';
            for(var i=0; i<wheelsData.length; i++){ //列
                tempHTML += '<div class="wheel"><ul class="selectContainer">';
                if(_this.jsonType){
                    for(var j=0; j<wheelsData[i].data.length; j++){ //行
                        tempHTML += '<li data-id="'+wheelsData[i].data[j].id+'">'+wheelsData[i].data[j].value+'</li>';
                    }
                }else{
                    for(var j=0; j<wheelsData[i].data.length; j++){ //行
                        tempHTML += '<li>'+wheelsData[i].data[j]+'</li>';
                    }
                }
                tempHTML += '</ul></div>';
            }
            _this.mobileSelect.querySelector('.wheels').innerHTML = tempHTML;
        },

        addListenerAll: function(){
            var _this = this;
            for(var i=0; i<_this.slider.length; i++){
                //手势监听
                (function (i) {
                    _this.addListenerWheel(_this.wheel[i], i);
                    _this.addListenerLi(i);
                })(i);
            }
        },

        addListenerWheel: function(theWheel, index){
            var _this = this;
            theWheel.addEventListener('touchstart', function () {
                _this.touch(event, this.firstChild, index);
            },false);
            theWheel.addEventListener('touchend', function () {
                _this.touch(event, this.firstChild, index);
            },false);
            theWheel.addEventListener('touchmove', function () {
                _this.touch(event, this.firstChild, index);
            },false);

            //PC拖拽监听
            theWheel.addEventListener('mousedown', function () {
                _this.dragClick(event, this.firstChild, index);
            },false);
            theWheel.addEventListener('mousemove', function () {
                _this.dragClick(event, this.firstChild, index);
            },false);
            theWheel.addEventListener('mouseup', function () {
                _this.dragClick(event, this.firstChild, index);
            },true);
        },

        addListenerLi:function(sliderIndex){
            var _this = this;
            var curWheelLi = _this.slider[sliderIndex].getElementsByTagName('li');
            for(var j=0; j<curWheelLi.length;j++){
                (function (j) {
                    curWheelLi[j].addEventListener('click',function(){
                        _this.singleClick(this, j, sliderIndex);
                    },false);
                })(j);
            }
        },

        checkDataType: function(){
            var _this = this;
            if(typeof(_this.wheelsData[0].data[0])=='object'){
                _this.jsonType = true;
                _this.cascadeJsonData = _this.wheelsData[0].data;
            }
        },

        checkCascade: function(){
            var _this = this;
            if(_this.jsonType){
                var node = _this.wheelsData[0].data;
                for(var i=0; i<node.length; i++){
                    if('childs' in node[i] && node[i].childs.length > 0){
                        _this.cascade = true;
                        break;
                    }
                }
            }else{
                _this.cascade = false;
            }
        },

        initCascade: function(){
            var _this = this;
            _this.displayJson.push(_this.generateArrData(_this.cascadeJsonData));
            if(_this.initPosition[0]){
                _this.checkArrDeep(_this.cascadeJsonData[_this.initPosition[0]]);
            }else{
                _this.checkArrDeep(_this.cascadeJsonData[0]);
            }
            _this.reRenderWheels();
        },

        generateArrData: function (targetArr) {
            var tempArr = [];
            for(var i=0; i<targetArr.length; i++){
                tempArr.push({
                    "id": targetArr[i].id,
                    "value": targetArr[i].value
                });
            }
            return tempArr;
        },

        checkArrDeep: function (parent) {
            //检测子节点深度  修改 displayJson
            var _this = this;
            if ('childs' in parent && parent.childs.length > 0) {
                _this.displayJson.push(_this.generateArrData(parent.childs)); //生成子节点数组
                _this.checkArrDeep(parent.childs[0]);//检测下一个子节点
            }
        },

        checkRange: function(index, posIndexArr){
            var _this = this;
            var deleteNum = _this.displayJson.length-1-index;
            for(var i=0; i<deleteNum; i++){
                _this.displayJson.pop(); //修改 displayJson
            }
            var resultNode;
            for (var i = 0; i <= index; i++){
                if (i == 0)
                    resultNode = _this.cascadeJsonData[posIndexArr[0]];
                else {
                    resultNode = resultNode.childs[posIndexArr[i]];
                }
            }
            _this.checkArrDeep(resultNode);
            //console.log(_this.displayJson);
            _this.reRenderWheels();
            _this.fixRowStyle();
            _this.setCurDistance(_this.resetPostion(index, posIndexArr));
        },

        resetPostion: function(index, posIndexArr){
            var _this = this;
            var tempPosArr = posIndexArr;
            var tempCount;
            if(_this.slider.length > posIndexArr.length){
                tempCount = _this.slider.length - posIndexArr.length;
                for(var i=0; i<tempCount; i++){
                    tempPosArr.push(0);
                }
            }else if(_this.slider.length < posIndexArr.length){
                tempCount = posIndexArr.length - _this.slider.length;
                for(var i=0; i<tempCount; i++){
                    tempPosArr.pop();
                }
            }
            for(var i=index+1; i< tempPosArr.length; i++){
                tempPosArr[i] = 0;
            }
            return tempPosArr;
        },

        reRenderWheels: function(){
            var _this = this;
            //删除多余的wheel
            if(_this.wheel.length > _this.displayJson.length){
                var count = _this.wheel.length - _this.displayJson.length;
                for(var i=0; i<count; i++){
                    _this.wheels.removeChild(_this.wheel[_this.wheel.length-1]);
                }
            }
            for(var i=0; i<_this.displayJson.length; i++){ //列
                (function (i) {
                    var tempHTML='';
                    if(_this.wheel[i]){
                        //console.log('插入Li');
                        for(var j=0; j<_this.displayJson[i].length; j++){ //行
                            tempHTML += '<li data-id="'+_this.displayJson[i][j].id+'">'+_this.displayJson[i][j].value+'</li>';
                        }
                        _this.slider[i].innerHTML = tempHTML;

                    }else{
                        var tempWheel = document.createElement("div");
                        tempWheel.className = "wheel";
                        tempHTML = '<ul class="selectContainer">';
                        for(var j=0; j<_this.displayJson[i].length; j++){ //行
                            tempHTML += '<li data-id="'+_this.displayJson[i][j].id+'">'+_this.displayJson[i][j].value+'</li>';
                        }
                        tempHTML += '</ul>';
                        tempWheel.innerHTML = tempHTML;

                        _this.addListenerWheel(tempWheel, i);
                        _this.wheels.appendChild(tempWheel);
                    }
                    _this.addListenerLi(i);
                })(i);
            }
        },

        updateWheels:function(data){
            var _this = this;
            if(_this.cascade){
                _this.cascadeJsonData = data;
                _this.displayJson = [];
                _this.initCascade();
                _this.setCurDistance(_this.initPosition);
                _this.fixRowStyle();
            }
        },

        updateWheel: function(sliderIndex, data){
            var _this = this;
            var tempHTML='';
            if(_this.cascade){
                console.error('级联格式不支持updateWheel(),请使用updateWheels()更新整个数据源');
                return false;
            }
            else if(_this.jsonType){
                for(var j=0; j<data.length; j++){
                    tempHTML += '<li data-id="'+data[j].id+'">'+data[j].value+'</li>';
                }
                _this.wheelsData[sliderIndex] = {data: data};
            }else{
                for(var j=0; j<data.length; j++){
                    tempHTML += '<li>'+data[j]+'</li>';
                }
                _this.wheelsData[sliderIndex] = data;
            }
            _this.slider[sliderIndex].innerHTML = tempHTML;
            _this.addListenerLi(sliderIndex);
        },

        fixRowStyle: function(){
            var _this = this;
            var width = (100/_this.wheel.length).toFixed(2);
            for(var i=0; i<_this.wheel.length; i++){
                _this.wheel[i].style.width = width+'%';
            }
        },

        getIndex: function(distance){
            return Math.round((2*this.liHeight-distance)/this.liHeight);
        },

        getIndexArr: function(){
            var _this = this;
            var temp = [];
            for(var i=0; i<_this.curDistance.length; i++){
                temp.push(_this.getIndex(_this.curDistance[i]));
            }
            return temp;
        },

        getResult: function(){
            var _this = this;
            var temp = [];
            var positionArr = _this.getIndexArr();
            if(_this.cascade){
                for(var i=0; i<_this.wheel.length; i++){
                    temp.push(_this.displayJson[i][positionArr[i]]);
                }
            }
            else if(_this.jsonType){
                for(var i=0; i<_this.curDistance.length; i++){
                    temp.push(_this.wheelsData[i].data[_this.getIndex(_this.curDistance[i])]);
                }
            }else{
                for(var i=0; i<_this.curDistance.length; i++){
                    temp.push(_this.getValue(i));
                }
            }
            return temp;
        },

        calcDistance: function(index){
            return 2*this.liHeight-index*this.liHeight;
        },

        setCurDistance: function(indexArr){
            var _this = this;
            var temp = [];
            for(var i=0; i<_this.slider.length; i++){
                temp.push(_this.calcDistance(indexArr[i]));
                _this.movePosition(_this.slider[i],temp[i]);
            }
            _this.curDistance = temp;
        },

        fixPosition: function(distance){
            return -(this.getIndex(distance)-2)*this.liHeight;
        },

        movePosition: function(theSlider, distance){
            theSlider.style.webkitTransform = 'translate3d(0,' + distance + 'px, 0)';
            theSlider.style.transform = 'translate3d(0,' + distance + 'px, 0)';
        },

        locatePostion: function(index, posIndex){
            this.curDistance[index] = this.calcDistance(posIndex);
            this.movePosition(this.slider[index],this.curDistance[index]);
        },

        updateCurDistance: function(theSlider, index){
            this.curDistance[index] = parseInt(theSlider.style.transform.split(',')[1]);
        },

        getDistance:function(theSlider){
            return parseInt(theSlider.style.transform.split(',')[1]);
        },

        getValue: function(sliderIndex){
            var _this = this;
            var index = _this.getIndex(_this.curDistance[sliderIndex]);
            return _this.slider[sliderIndex].getElementsByTagName('li')[index].innerHTML;
        },

        touch: function(event, theSlider, index){
            var _this = this;
            event = event || window.event;
            switch(event.type){
                case "touchstart":
                    _this.startY = event.touches[0].clientY;
                    _this.oldMoveY = _this.startY;
                    break;

                case "touchend":

                    _this.moveEndY = event.changedTouches[0].clientY;
                    _this.offsetSum = _this.moveEndY - _this.startY;

                    //修正位置
                    _this.updateCurDistance(theSlider, index);
                    _this.curDistance[index] = _this.fixPosition(_this.curDistance[index]);
                    _this.movePosition(theSlider, _this.curDistance[index]);
                    _this.oversizeBorder = -(theSlider.getElementsByTagName('li').length-3)*_this.liHeight;


                    //反弹
                    if(_this.curDistance[index] + _this.offsetSum > 2*_this.liHeight){
                        _this.curDistance[index] = 2*_this.liHeight;
                        setTimeout(function(){
                            _this.movePosition(theSlider, _this.curDistance[index]);
                        }, 100);

                    }else if(_this.curDistance[index] + _this.offsetSum < _this.oversizeBorder){
                        _this.curDistance[index] = _this.oversizeBorder;
                        setTimeout(function(){
                            _this.movePosition(theSlider, _this.curDistance[index]);
                        }, 100);
                    }


                    _this.transitionEnd(_this.getIndexArr(),_this.getResult());

                    if(_this.cascade){
                        var tempPosArr = _this.getIndexArr();
                        tempPosArr[index] = _this.getIndex(_this.curDistance[index]);
                        _this.checkRange(index, tempPosArr);
                    }

                    break;

                case "touchmove":
                    event.preventDefault();
                    _this.moveY = event.touches[0].clientY;
                    _this.offset = _this.moveY - _this.oldMoveY;

                    _this.updateCurDistance(theSlider, index);
                    _this.curDistance[index] = _this.curDistance[index] + _this.offset;
                    _this.movePosition(theSlider, _this.curDistance[index]);
                    _this.oldMoveY = _this.moveY;
                    break;
            }
        },

        dragClick: function(event, theSlider, index){
            var _this = this;
            event = event || window.event;
            switch(event.type){
                case "mousedown":
                    _this.startY = event.clientY;
                    _this.oldMoveY = _this.startY;
                    _this.clickStatus = true;
                    break;

                case "mouseup":

                    _this.moveEndY = event.clientY;
                    _this.offsetSum = _this.moveEndY - _this.startY;

                    //修正位置
                    _this.updateCurDistance(theSlider, index);
                    _this.curDistance[index] = _this.fixPosition(_this.curDistance[index]);
                    _this.movePosition(theSlider, _this.curDistance[index]);
                    _this.oversizeBorder = -(theSlider.getElementsByTagName('li').length-3)*_this.liHeight;


                    //反弹
                    if(_this.curDistance[index] + _this.offsetSum > 2*_this.liHeight){
                        _this.curDistance[index] = 2*_this.liHeight;
                        setTimeout(function(){
                            _this.movePosition(theSlider, _this.curDistance[index]);
                        }, 100);

                    }else if(_this.curDistance[index] + _this.offsetSum < _this.oversizeBorder){
                        _this.curDistance[index] = _this.oversizeBorder;
                        setTimeout(function(){
                            _this.movePosition(theSlider, _this.curDistance[index]);
                        }, 100);
                    }

                    _this.clickStatus = false;
                    _this.transitionEnd(_this.getIndexArr(),_this.getResult());
                    if(_this.cascade){
                        var tempPosArr = _this.getIndexArr();
                        tempPosArr[index] = _this.getIndex(_this.curDistance[index]);
                        _this.checkRange(index, tempPosArr);
                    }
                    break;

                case "mousemove":
                    event.preventDefault();
                    if(_this.clickStatus){
                        _this.moveY = event.clientY;
                        _this.offset = _this.moveY - _this.oldMoveY;
                        _this.updateCurDistance(theSlider, index);
                        _this.curDistance[index] = _this.curDistance[index] + _this.offset;
                        _this.movePosition(theSlider, _this.curDistance[index]);
                        _this.oldMoveY = _this.moveY;
                    }
                    break;
            }
        },

        singleClick: function(theLi, index, sliderIndex){
            var _this = this;
            if(_this.cascade){
                var tempPosArr = _this.getIndexArr();
                tempPosArr[sliderIndex] = index;
                _this.checkRange(sliderIndex, tempPosArr);

            }else{
                _this.curDistance[sliderIndex] = (2-index)*_this.liHeight;
                _this.movePosition(theLi.parentNode, _this.curDistance[sliderIndex]);
            }
        }

    };

    return MobileSelect;
})();